home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 7 / FM Towns Free Software Collection 7.iso / taropyon / zmodem / src / zm.c < prev    next >
C/C++ Source or Header  |  1993-11-30  |  21KB  |  995 lines

  1. /*
  2.  * Z M . C ZMODEM protocol primitives 05-24-89    Chuck Forsberg Omen
  3.  * Technology Inc
  4.  *
  5.  * Entry point Functions: zsbhdr(type, hdr) send binary header zshhdr(type, hdr)
  6.  * send hex header zgethdr(hdr, eflag) receive header - binary or hex
  7.  * zsdata(buf, len, frameend) send data zrdata(buf, len) receive data
  8.  * stohdr(pos) store position data in Txhdr long rclhdr(hdr) recover position
  9.  * offset from header
  10.  *
  11.  *
  12.  * This version implements numerous enhancements including ZMODEM Run Length
  13.  * Encoding and variable length headers.  These features were not funded by
  14.  * the original Telenet development contract.
  15.  *
  16.  * This software may be freely used for non commercial and educational (didactic
  17.  * only) purposes.    This software may also be freely used to support file
  18.  * transfer operations to or from licensed Omen Technology products.  Any
  19.  * programs which use part or all of this software must be provided in source
  20.  * form with this notice intact except by written permission from Omen
  21.  * Technology Incorporated.
  22.  *
  23.  * Use of this software for commercial or administrative purposes except when
  24.  * exclusively limited to interfacing Omen Technology products requires a per
  25.  * port license payment of $20.00 US per port (less in quantity).  Use of
  26.  * this code by inclusion, decompilation, reverse engineering or any other
  27.  * means constitutes agreement to these conditions and acceptance of
  28.  * liability to license the materials and payment of reasonable legal costs
  29.  * necessary to enforce this license agreement.
  30.  *
  31.  *
  32.  * Omen Technology Inc            FAX: 503-621-3745 Post Office Box 4681
  33.  * Portland OR 97208
  34.  *
  35.  * This code is made available in the hope it will be useful, BUT WITHOUT ANY
  36.  * WARRANTY OF ANY KIND OR LIABILITY FOR ANY DAMAGES OF ANY KIND.
  37.  *
  38.  */
  39.  
  40. #ifndef CANFDX
  41. #include "zmodem.h"
  42. int         Rxtimeout = 100;    /* Tenths of seconds to wait for something */
  43. #endif
  44.  
  45. #ifndef UNSL
  46. #define UNSL
  47. #endif
  48.  
  49.  
  50. /* Globals used by ZMODEM functions */
  51. int         Rxframeind;         /* ZBIN ZBIN32, or ZHEX type of frame */
  52. int         Rxtype;             /* Type of header received */
  53. int         Rxhlen;             /* Length of header received */
  54. int         Rxcount;            /* Count of data bytes received */
  55. char        Rxhdr[ZMAXHLEN];    /* Received header */
  56. char        Txhdr[ZMAXHLEN];    /* Transmitted header */
  57. long        Rxpos;                /* Received file position */
  58. long        Txpos;                /* Transmitted file position */
  59. int         Txfcs32;            /* TURE means send binary frames with 32 bit
  60.                                  * FCS */
  61. int         Crc32t;             /* Controls 32 bit CRC being sent */
  62.                                 /* 1 == CRC32,    2 == CRC32 + RLE */
  63. int         Crc32r;             /* Indicates/controls 32 bit CRC being received */
  64.                                 /* 0 == CRC16,    1 == CRC32,  2 == CRC32 + RLE */
  65. int         Usevhdrs;            /* Use variable length headers */
  66. int         Znulls;             /* Number of nulls to send at beginning of
  67.                                  * ZDATA hdr */
  68. char        Attn[ZATTNLEN + 1]; /* Attention string rx sends to tx on err */
  69. char       *Altcan;             /* Alternate canit string */
  70.  
  71. static        lastsent;            /* Last char we sent */
  72. static        Not8bit;            /* Seven bits seen on header */
  73.  
  74. static char *frametypes[] =
  75. {
  76.     "No Response to Error Correction Request",    /* -4 */
  77.     "No Carrier Detect",        /* -3 */
  78.     "TIMEOUT",                    /* -2 */
  79.     "ERROR",                    /* -1 */
  80. #define FTOFFSET 4
  81.     "ZRQINIT",
  82.     "ZRINIT",
  83.     "ZSINIT",
  84.     "ZACK",
  85.     "ZFILE",
  86.     "ZSKIP",
  87.     "ZNAK",
  88.     "ZABORT",
  89.     "ZFIN",
  90.     "ZRPOS",
  91.     "ZDATA",
  92.     "ZEOF",
  93.     "ZFERR",
  94.     "ZCRC",
  95.     "ZCHALLENGE",
  96.     "ZCOMPL",
  97.     "ZCAN",
  98.     "ZFREECNT",
  99.     "ZCOMMAND",
  100.     "ZSTDERR",
  101.     "xxxxx"
  102. #define FRTYPES 22                /* Total number of frame types in this array */
  103. /* not including psuedo negative entries */
  104. };
  105.  
  106. static char badcrc[] = "Bad CRC";
  107.  
  108. /* Send ZMODEM binary header hdr of type type */
  109. void    zsbhdr(int len, int type, register char *hdr)
  110. {
  111.     register int n;
  112.     register unsigned short crc;
  113.  
  114. #ifndef DSZ
  115.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs ? 'v' : 'f', len,
  116.           frametypes[type + FTOFFSET], rclhdr(hdr));
  117. #endif
  118.     if (type == ZDATA)
  119.     {
  120.         for (n = Znulls; --n >= 0;)
  121.             xsendline(0);
  122.     }
  123.  
  124.     xsendline(ZPAD);
  125.     xsendline(ZDLE);
  126.  
  127.     switch ( Crc32t = Txfcs32 )
  128.     {
  129.         case 2:
  130.             zsbh32(len, hdr, type, Usevhdrs ? ZVBINR32 : ZBINR32);
  131.             flushmo();
  132.             break;
  133.         case 1:
  134.             zsbh32(len, hdr, type, Usevhdrs ? ZVBIN32 : ZBIN32);
  135.             break;
  136.         default:
  137.             if (Usevhdrs)
  138.             {
  139.                 xsendline(ZVBIN);
  140.                 zsendline(len);
  141.             } else
  142.                 xsendline(ZBIN);
  143.             zsendline(type);
  144.             crc = updcrc(type, 0);
  145.  
  146.             for (n = len; --n >= 0; ++hdr)
  147.             {
  148.                 zsendline( (*hdr) & 0xFF );
  149.                 crc = updcrc((0377 & *hdr), crc);
  150.             }
  151.             crc = updcrc(0, updcrc(0, crc));
  152.             zsendline(crc >> 8);
  153.             zsendline(crc);
  154.     }
  155.     if (type != ZDATA)
  156.         flushmo();
  157. }
  158.  
  159.  
  160. /* Send ZMODEM binary header hdr of type type */
  161. void    zsbh32(int len, register char *hdr, int type, int flavour)
  162. {
  163.     register int n;
  164.     register UNSL long crc;
  165.  
  166.     xsendline(flavour);
  167.     if (Usevhdrs)
  168.         zsendline(len);
  169.     zsendline(type);
  170.     crc = 0xFFFF_FFFFL;
  171.     crc = UPDC32(type, crc);
  172.  
  173.     for (n = len; --n >= 0; ++hdr)
  174.     {
  175.         crc = UPDC32((0377 & *hdr), crc);
  176.         zsendline( (*hdr) & 0xFF );
  177.     }
  178.     crc = ~crc;
  179.     for (n = 4; --n >= 0;)
  180.     {
  181.         zsendline((int) crc);
  182.         crc >>= 8;
  183.     }
  184. }
  185.  
  186. /* Send ZMODEM HEX header hdr of type type */
  187. void    zshhdr(int len, int type, register char *hdr)
  188. {
  189.     register int n;
  190.     register unsigned short crc;
  191.  
  192. #ifndef DSZ
  193.     vfile("zshhdr: %c %d %s %lx", Usevhdrs ? 'v' : 'f', len,
  194.           frametypes[type + FTOFFSET], rclhdr(hdr));
  195. #endif
  196.     sendline(ZPAD);
  197.     sendline(ZPAD);
  198.     sendline(ZDLE);
  199.     if (Usevhdrs)
  200.     {
  201.         sendline(ZVHEX);
  202.         zputhex(len);
  203.     } else
  204.         sendline(ZHEX);
  205.     zputhex(type);
  206.     Crc32t = 0;
  207.  
  208.     crc = updcrc(type, 0);
  209.     for (n = len; --n >= 0; ++hdr)
  210.     {
  211.         zputhex(*hdr);
  212.         crc = updcrc((0377 & *hdr), crc);
  213.     }
  214.     crc = updcrc(0, updcrc(0, crc));
  215.     zputhex(crc >> 8);
  216.     zputhex(crc);
  217.  
  218.     /* Make it printable on remote machine */
  219.     sendline(015);
  220.     sendline(0212);
  221.     /*
  222.      * Uncork the remote in case a fake XOFF has stopped data flow
  223.      */
  224.     if (type != ZFIN && type != ZACK)
  225.         sendline(021);
  226.     flushmo();
  227. }
  228.  
  229. /*
  230.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  231.  */
  232. static char *Zendnames[] = {"ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  233. void    zsdata(register char *buf, int length, int frameend)
  234. {
  235.     register unsigned short crc;
  236.  
  237. #ifndef DSZ
  238.     vfile("zsdata: %d %s", length, Zendnames[frameend - ZCRCE & 3]);
  239. #endif
  240. #ifdef    DEBUG
  241.     USR_fprintf(stderr,"zsdata: Crc32t = %d\n", Crc32t );
  242. #endif
  243.     switch (Crc32t)
  244.     {
  245.         case 1:
  246.             zsda32(buf, length, frameend);
  247.             break;
  248.         case 2:
  249.             zsdar32(buf, length, frameend);
  250.             break;
  251.         default:
  252.             crc = 0;
  253.             for (; --length >= 0; ++buf)
  254.             {
  255.                 zsendline( (*buf)&0xFF );
  256.                 crc = updcrc((0377 & *buf), crc);
  257.             }
  258.             xsendline(ZDLE);
  259.             xsendline(frameend);
  260.             crc = updcrc(frameend, crc);
  261.  
  262.             crc = updcrc(0, updcrc(0, crc));
  263.             zsendline(crc >> 8);
  264.             zsendline(crc);
  265.     }
  266.     if (frameend == ZCRCW)
  267.         xsendline(XON);
  268.     if (frameend != ZCRCG)
  269.         flushmo();
  270. }
  271.  
  272. void    zsda32(register char *buf, int length, int frameend)
  273. {
  274.     register int c;
  275.     register UNSL long crc;
  276.  
  277.     crc = 0xFFFFFFFFL;
  278.     for (; --length >= 0; ++buf)
  279.     {
  280.         c = (*buf) & 0377;
  281.         if (c & 0140)
  282.             xsendline(lastsent = c);
  283.         else
  284.             zsendline(c);
  285.         crc = UPDC32(c, crc);
  286.     }
  287.     xsendline(ZDLE);
  288.     xsendline(frameend);
  289.     crc = UPDC32(frameend, crc);
  290.  
  291.     crc = ~crc;
  292.     for (c = 4; --c >= 0;)
  293.     {
  294.         zsendline((int) crc);
  295.         crc >>= 8;
  296.     }
  297. }
  298.  
  299. /*
  300.  * Receive array buf of max length with ending ZDLE sequence and CRC.
  301.  * Returns the ending character or error code. NB: On errors may store
  302.  * length+1 bytes!
  303.  */
  304. int        zrdata(register char *buf, int length)
  305. {
  306.     register int c;
  307.     register unsigned short crc;
  308.     register char *end;
  309.     register int d;
  310.  
  311.     switch (Crc32r)
  312.     {
  313.         case 1:
  314.             return zrdat32(buf, length);
  315.         case 2:
  316.             return zrdatr32(buf, length);
  317.     }
  318.  
  319.     crc = Rxcount = 0;
  320.     end = buf + length;
  321.     while (buf <= end)
  322.     {
  323.         if ((c = zdlread()) & ~0377)
  324.         {
  325.           crcfoo:
  326.             switch (c)
  327.             {
  328.                 case GOTCRCE:
  329.                 case GOTCRCG:
  330.                 case GOTCRCQ:
  331.                 case GOTCRCW:
  332.                     crc = updcrc((d = c) & 0377, crc);
  333.                     if ((c = zdlread()) & ~0377)
  334.                         goto crcfoo;
  335.                     crc = updcrc(c, crc);
  336.                     if ((c = zdlread()) & ~0377)
  337.                         goto crcfoo;
  338.                     crc = updcrc(c, crc);
  339.                     if (crc & 0xFFFF)
  340.                     {
  341.                         zperr(badcrc);
  342.                         return ERROR;
  343.                     }
  344.                     Rxcount = length - (end - buf);
  345. #ifndef DSZ
  346.                     vfile("zrdata: %d  %s", Rxcount,
  347.                           Zendnames[d - GOTCRCE & 3]);
  348. #endif
  349.                     return d;
  350.                 case GOTCAN:
  351.                     zperr("Sender Canceled");
  352.                     return ZCAN;
  353.                 case TIMEOUT:
  354.                     zperr("TIMEOUT");
  355.                     return c;
  356.                 default:
  357.                     garbitch();
  358.                     return c;
  359.             }
  360.         }
  361.         *buf++ = c;
  362.         crc = updcrc(c, crc);
  363.     }
  364. #ifdef DSZ
  365.     garbitch();
  366. #else
  367.     zperr("Data subpacket too long");
  368. #endif
  369.     return ERROR;
  370. }
  371.  
  372. int        zrdat32(register char *buf, int length)
  373. {
  374.     register int c;
  375.     register UNSL long crc;
  376.     register char *end;
  377.     register int d;
  378.  
  379.     crc = 0xFFFF_FFFFL;
  380.     Rxcount = 0;
  381.     end = buf + length;
  382.     while ( buf <= end )
  383.     {
  384.         if ((c = zdlread()) & ~0377)
  385.         {
  386.           crcfoo:
  387.             switch (c)
  388.             {
  389.                 case GOTCRCE:
  390.                 case GOTCRCG:
  391.                 case GOTCRCQ:
  392.                 case GOTCRCW:
  393.                     d = c;
  394.                     c &= 0377;
  395.                     crc = UPDC32(c, crc);
  396.                     if ((c = zdlread()) & ~0377)
  397.                         goto crcfoo;
  398.                     crc = UPDC32(c, crc);
  399.                     if ((c = zdlread()) & ~0377)
  400.                         goto crcfoo;
  401.                     crc = UPDC32(c, crc);
  402.                     if ((c = zdlread()) & ~0377)
  403.                         goto crcfoo;
  404.                     crc = UPDC32(c, crc);
  405.                     if ((c = zdlread()) & ~0377)
  406.                         goto crcfoo;
  407.                     crc = UPDC32(c, crc);
  408.                     if (crc != 0xDEBB_20E3)
  409.                     {
  410.                         zperr(badcrc);
  411.                         return ERROR;
  412.                     }
  413.                     Rxcount = length - (end - buf);
  414. #ifndef DSZ
  415.                     vfile("zrdat32: %d %s", Rxcount,
  416.                           Zendnames[d - GOTCRCE & 3]);
  417. #endif
  418.                     return d;
  419.                 case GOTCAN:
  420.                     zperr("Sender Canceled");
  421.                     return ZCAN;
  422.                 case TIMEOUT:
  423.                     zperr("TIMEOUT");
  424.                     return c;
  425.                 default:
  426.                     garbitch();
  427.                     return c;
  428.             }
  429.         }
  430.         *buf++ = c;
  431.         crc = UPDC32(c, crc);
  432.     }
  433.     zperr("Data subpacket too long");
  434.     return ERROR;
  435. }
  436.  
  437. void    garbitch(void)
  438. {
  439.     zperr("Garbled data subpacket");
  440. }
  441.  
  442. /*
  443.  * Read a ZMODEM header to hdr, either binary or hex. eflag controls local
  444.  * display of non zmodem characters: 0:  no display 1:    display printing
  445.  * characters only 2:  display all non ZMODEM characters
  446.  *
  447.  * Set Rxhlen to size of header (default 4) (valid iff good hdr) On success, set
  448.  * Zmodem to 1, set Rxpos and return type of header. Otherwise return
  449.  * negative on error. Return ERROR instantly if ZCRCW sequence, for fast
  450.  * error recovery.
  451.  */
  452. int        zgethdr(char *hdr, int eflag)
  453. {
  454.     register int c, n, cancount;
  455.  
  456.     n = Zrwindow + Effbaud;     /* Max bytes before start of frame */
  457.     Rxframeind = Rxtype = 0;
  458.  
  459.   startover:
  460.     cancount = 5;
  461.   again:
  462.     /* Return immediate ERROR if ZCRCW sequence seen */
  463.     switch (c = readline(Rxtimeout))
  464.     {
  465.         case 021:
  466.         case 0221:
  467.             goto again;
  468.         case RCDO:
  469.         case TIMEOUT:
  470.             goto fifi;
  471.         case CAN:
  472.           gotcan:
  473.             if (--cancount <= 0)
  474.             {
  475.                 c = ZCAN;
  476.                 goto fifi;
  477.             }
  478.             switch (c = readline(1))
  479.             {
  480.                 case TIMEOUT:
  481.                     goto again;
  482.                 case ZCRCW:
  483.                     switch (readline(1))
  484.                     {
  485.                         case TIMEOUT:
  486.                             c = ERROR;
  487.                             goto fifi;
  488.                         case RCDO:
  489.                             goto fifi;
  490.                         default:
  491.                             goto agn2;
  492.                     }
  493.                 case RCDO:
  494.                     goto fifi;
  495.                 default:
  496.                     break;
  497.                 case CAN:
  498.                     if (--cancount <= 0)
  499.                     {
  500.                         c = ZCAN;
  501.                         goto fifi;
  502.                     }
  503.                     goto again;
  504.             }
  505.             /* **** FALL THRU TO **** */
  506.         default:
  507.           agn2:
  508.             if (--n == 0)
  509.             {
  510.                 c = GCOUNT;
  511.                 goto fifi;
  512.             }
  513.             if (eflag && ((c &= 0177) & 0140))
  514.                 bttyout(c);
  515.             else if (eflag > 1)
  516.                 bttyout(c);
  517. #ifdef UNIX
  518.             fflush(stderr);
  519. #endif
  520.             goto startover;
  521.         case ZPAD | 0200:        /* This is what we want. */
  522.             Not8bit = c;
  523.         case ZPAD:                /* This is what we want. */
  524.             break;
  525.     }
  526.     cancount = 5;
  527.   splat:
  528.     switch (c = noxrd7())
  529.     {
  530.         case ZPAD:
  531.             goto splat;
  532.         case RCDO:
  533.         case TIMEOUT:
  534.             goto fifi;
  535.         default:
  536.             goto agn2;
  537.         case ZDLE:                /* This is what we want. */
  538.             break;
  539.     }
  540.  
  541.  
  542.     Rxhlen = 4;                 /* Set default length */
  543.     Rxframeind = c = noxrd7();
  544.     switch (c)
  545.     {
  546.         case ZVBIN32:
  547.             if ((Rxhlen = c = zdlread()) < 0)
  548.                 goto fifi;
  549.             if (c > ZMAXHLEN)
  550.                 goto agn2;
  551.             Crc32r = 1;
  552.             c = zrbhd32(hdr);
  553.             break;
  554.         case ZBIN32:
  555.             if (Usevhdrs)
  556.                 goto agn2;
  557.             Crc32r = 1;
  558.             c = zrbhd32(hdr);
  559.             break;
  560.         case ZVBINR32:
  561.             if ((Rxhlen = c = zdlread()) < 0)
  562.                 goto fifi;
  563.             if (c > ZMAXHLEN)
  564.                 goto agn2;
  565.             Crc32r = 2;
  566.             c = zrbhd32(hdr);
  567.             break;
  568.         case ZBINR32:
  569.             if (Usevhdrs)
  570.                 goto agn2;
  571.             Crc32r = 2;
  572.             c = zrbhd32(hdr);
  573.             break;
  574.         case RCDO:
  575.         case TIMEOUT:
  576.             goto fifi;
  577.         case ZVBIN:
  578.             if ((Rxhlen = c = zdlread()) < 0)
  579.                 goto fifi;
  580.             if (c > ZMAXHLEN)
  581.                 goto agn2;
  582.             Crc32r = 0;
  583.             c = zrbhdr(hdr);
  584.             break;
  585.         case ZBIN:
  586.             if (Usevhdrs)
  587.                 goto agn2;
  588.             Crc32r = 0;
  589.             c = zrbhdr(hdr);
  590.             break;
  591.         case ZVHEX:
  592.             if ((Rxhlen = c = zgethex()) < 0)
  593.                 goto fifi;
  594.             if (c > ZMAXHLEN)
  595.                 goto agn2;
  596.             Crc32r = 0;
  597.             c = zrhhdr(hdr);
  598.             break;
  599.         case ZHEX:
  600.             if (Usevhdrs)
  601.                 goto agn2;
  602.             Crc32r = 0;
  603.             c = zrhhdr(hdr);
  604.             break;
  605.         case CAN:
  606.             goto gotcan;
  607.         default:
  608.             goto agn2;
  609.     }
  610.     for (n = Rxhlen; ++n < ZMAXHLEN;)    /* Clear unused hdr bytes */
  611.         hdr[n] = 0;
  612.     Rxpos = hdr[ZP3] & 0377;
  613.     Rxpos = (Rxpos << 8) + (hdr[ZP2] & 0377);
  614.     Rxpos = (Rxpos << 8) + (hdr[ZP1] & 0377);
  615.     Rxpos = (Rxpos << 8) + (hdr[ZP0] & 0377);
  616. #ifdef    DEBUG
  617.     USR_fprintf(stderr,"Rxpos = %10ld (hdr = %02X %02X %02X %02X)\n",
  618.         Rxpos, hdr[0], hdr[1], hdr[2], hdr[3] );
  619. #endif
  620.   fifi:
  621.     switch (c)
  622.     {
  623.         case GOTCAN:
  624.             c = ZCAN;
  625.             /* **** FALL THRU TO **** */
  626.         case ZNAK:
  627.         case ZCAN:
  628.         case ERROR:
  629.         case TIMEOUT:
  630.         case RCDO:
  631.         case GCOUNT:
  632.             zperr("Got %s", frametypes[c + FTOFFSET]);
  633.             /* **** FALL THRU TO **** */
  634. #ifndef DSZ
  635.         default:
  636.             if (c >= -4 && c <= FRTYPES)
  637.                 vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  638.                       frametypes[c + FTOFFSET], Rxpos);
  639.             else
  640.                 vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  641. #endif
  642.     }
  643.     /* Use variable length headers if we got one */
  644.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  645.         Usevhdrs = 1;
  646.     return c;
  647. }
  648.  
  649. /* Receive a binary style header (type and position) */
  650. int        zrbhdr(register char *hdr)
  651. {
  652.     register int c, n;
  653.     register unsigned short crc;
  654.  
  655.     if ((c = zdlread()) & ~0377)
  656.         return c;
  657.     Rxtype = c;
  658.     crc = updcrc(c, 0);
  659.  
  660.     for (n = Rxhlen; --n >= 0; ++hdr)
  661.     {
  662.         if ((c = zdlread()) & ~0377)
  663.             return c;
  664.         crc = updcrc(c, crc);
  665.         *hdr = c;
  666.     }
  667.     if ((c = zdlread()) & ~0377)
  668.         return c;
  669.     crc = updcrc(c, crc);
  670.     if ((c = zdlread()) & ~0377)
  671.         return c;
  672.     crc = updcrc(c, crc);
  673.     if (crc & 0xFFFF)
  674.     {
  675.         zperr(badcrc);
  676.         return ERROR;
  677.     }
  678. #ifdef ZMODEM
  679.     Protocol = ZMODEM;
  680. #endif
  681.     Zmodem = 1;
  682.     return Rxtype;
  683. }
  684.  
  685. /* Receive a binary style header (type and position) with 32 bit FCS */
  686. int        zrbhd32(register char *hdr)
  687. {
  688.     register int c, n;
  689.     register UNSL long crc;
  690.  
  691.     if ((c = zdlread()) & ~0377)
  692.         return c;
  693.     Rxtype = c;
  694.     crc = 0xFFFFFFFFL;
  695.     crc = UPDC32(c, crc);
  696. #ifdef DEBUGZ
  697.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  698. #endif
  699.  
  700.     for (n = Rxhlen; --n >= 0; ++hdr)
  701.     {
  702.         if ((c = zdlread()) & ~0377)
  703.             return c;
  704.         crc = UPDC32(c, crc);
  705.         *hdr = c;
  706. #ifdef DEBUGZ
  707.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  708. #endif
  709.     }
  710.     for (n = 4; --n >= 0;)
  711.     {
  712.         if ((c = zdlread()) & ~0377)
  713.             return c;
  714.         crc = UPDC32(c, crc);
  715. #ifdef DEBUGZ
  716.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  717. #endif
  718.     }
  719.     if (crc != 0xDEBB20E3)
  720.     {
  721.         zperr(badcrc);
  722.         return ERROR;
  723.     }
  724. #ifdef ZMODEM
  725.     Protocol = ZMODEM;
  726. #endif
  727.     Zmodem = 1;
  728.     return Rxtype;
  729. }
  730.  
  731.  
  732. /* Receive a hex style header (type and position) */
  733. int        zrhhdr(char *hdr)
  734. {
  735.     register int c;
  736.     register unsigned short crc;
  737.     register int n;
  738.  
  739.     if ((c = zgethex()) < 0)
  740.         return c;
  741.     Rxtype = c;
  742.     crc = updcrc(c, 0);
  743.  
  744.     for (n = Rxhlen; --n >= 0; ++hdr)
  745.     {
  746.         if ((c = zgethex()) < 0)
  747.             return c;
  748.         crc = updcrc(c, crc);
  749.         *hdr = c;
  750.     }
  751.     if ((c = zgethex()) < 0)
  752.         return c;
  753.     crc = updcrc(c, crc);
  754.     if ((c = zgethex()) < 0)
  755.         return c;
  756.     crc = updcrc(c, crc);
  757.     if (crc & 0xFFFF)
  758.     {
  759.         zperr(badcrc);
  760.         return ERROR;
  761.     }
  762.     switch (c = readline(2))
  763.     {
  764.         case 0215:
  765.             Not8bit = c;
  766.             /* **** FALL THRU TO **** */
  767.         case 015:
  768.             /* Throw away possible cr/lf */
  769.             switch (c = readline(2))
  770.             {
  771.                 case 012:
  772.                     Not8bit |= c;
  773.             }
  774.     }
  775. #ifdef ZMODEM
  776.     Protocol = ZMODEM;
  777. #endif
  778.     Zmodem = 1;
  779.     if (c < 0)
  780.         return c;
  781.     return Rxtype;
  782. }
  783.  
  784. /* Send a byte as two hex digits */
  785. void    zputhex(register int c)
  786. {
  787.     static char digits[] = "0123456789abcdef";
  788.  
  789. #ifdef DEBUGZ
  790.     if (Verbose > 8)
  791.         vfile("zputhex: %02X", c);
  792. #endif
  793.     sendline(digits[(c & 0xF0) >> 4]);
  794.     sendline(digits[(c) & 0xF]);
  795. }
  796.  
  797. /*
  798.  * Send character c with ZMODEM escape sequence encoding. Escape XON, XOFF.
  799.  * Escape CR following @ (Telenet net escape)
  800.  */
  801. void    zsendline(int c)
  802. {
  803.     c &= 0xFF;
  804.     /* Quick check for non control characters */
  805.     if (c & 0140)
  806.         xsendline(lastsent = c);
  807.     else
  808.     {
  809.         switch (c &= 0377)
  810.         {
  811.             case ZDLE:
  812.                 xsendline(ZDLE);
  813.                 xsendline(lastsent = (c ^= 0100));
  814.                 break;
  815.             case 015:
  816.             case 0215:
  817.                 if (!Zctlesc && (lastsent & 0177) != '@')
  818.                     goto sendit;
  819.                 /* **** FALL THRU TO **** */
  820.             case 020:
  821.             case 021:
  822.             case 023:
  823.             case 0220:
  824.             case 0221:
  825.             case 0223:
  826.                 xsendline(ZDLE);
  827.                 c ^= 0100;
  828.               sendit:
  829.                 xsendline(lastsent = c);
  830.                 break;
  831.             default:
  832.                 if (Zctlesc && !(c & 0140))
  833.                 {
  834.                     xsendline(ZDLE);
  835.                     c ^= 0100;
  836.                 }
  837.                 xsendline(lastsent = c);
  838.         }
  839.     }
  840. }
  841.  
  842. /* Decode two lower case hex digits into an 8 bit byte value */
  843. int        zgethex(void)
  844. {
  845.     register int c;
  846.  
  847.     c = zgeth1();
  848. #ifdef DEBUGZ
  849.     if (Verbose > 8)
  850.         vfile("zgethex: %02X", c);
  851. #endif
  852.     return c;
  853. }
  854. int        zgeth1(void)
  855. {
  856.     register int c, n;
  857.  
  858.     if ((c = noxrd7()) < 0)
  859.         return c;
  860.     n = c - '0';
  861.     if (n > 9)
  862.         n -= ('a' - ':');
  863.     if (n & ~0xF)
  864.         return ERROR;
  865.     if ((c = noxrd7()) < 0)
  866.         return c;
  867.     c -= '0';
  868.     if (c > 9)
  869.         c -= ('a' - ':');
  870.     if (c & ~0xF)
  871.         return ERROR;
  872.     c += (n << 4);
  873.     return c;
  874. }
  875.  
  876. /*
  877.  * Read a byte, checking for ZMODEM escape encoding including CAN*5 which
  878.  * represents a quick abort
  879.  */
  880. int        zdlread(void)
  881. {
  882.     register int c;
  883.  
  884.   again:
  885.     /* Quick check for non control characters */
  886.     if ((c = readline(Rxtimeout)) & 0140)
  887.         return c;
  888.     switch (c)
  889.     {
  890.         case ZDLE:
  891.             break;
  892.         case 023:
  893.         case 0223:
  894.         case 021:
  895.         case 0221:
  896.             goto again;
  897.         default:
  898.             if (Zctlesc && !(c & 0140))
  899.             {
  900.                 goto again;
  901.             }
  902.             return c;
  903.     }
  904.   again2:
  905.     if ((c = readline(Rxtimeout)) < 0)
  906.         return c;
  907.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  908.         return c;
  909.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  910.         return c;
  911.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  912.         return c;
  913.     switch (c)
  914.     {
  915.         case CAN:
  916.             return GOTCAN;
  917.         case ZCRCE:
  918.         case ZCRCG:
  919.         case ZCRCQ:
  920.         case ZCRCW:
  921.             return (c | GOTOR);
  922.         case ZRUB0:
  923.             return 0177;
  924.         case ZRUB1:
  925.             return 0377;
  926.         case 023:
  927.         case 0223:
  928.         case 021:
  929.         case 0221:
  930.             goto again2;
  931.         default:
  932.             if (Zctlesc && !(c & 0140))
  933.             {
  934.                 goto again2;
  935.             }
  936.             if ((c & 0140) == 0100)
  937.                 return (c ^ 0100);
  938.             break;
  939.     }
  940.     if (Verbose > 1)
  941.         zperr("Bad escape sequence %x", c);
  942.     return ERROR;
  943. }
  944.  
  945. /*
  946.  * Read a character from the modem line with timeout. Eat parity, XON and
  947.  * XOFF characters.
  948.  */
  949. int        noxrd7(void)
  950. {
  951.     register int c;
  952.  
  953.     for (;;)
  954.     {
  955.         if ((c = readline(Rxtimeout)) < 0)
  956.             return c;
  957.         switch (c &= 0177)
  958.         {
  959.             case XON:
  960.             case XOFF:
  961.                 continue;
  962.             default:
  963.                 if (Zctlesc && !(c & 0140))
  964.                     continue;
  965.             case '\r':
  966.             case '\n':
  967.             case ZDLE:
  968.                 return c;
  969.         }
  970.     }
  971. }
  972.  
  973. /* Store long integer pos in Txhdr */
  974. void    stohdr(long pos)
  975. {
  976.     Txhdr[ZP0] = pos;
  977.     Txhdr[ZP1] = pos >> 8;
  978.     Txhdr[ZP2] = pos >> 16;
  979.     Txhdr[ZP3] = pos >> 24;
  980. }
  981.  
  982. /* Recover a long integer from a header */
  983. long    rclhdr(register char *hdr)
  984. {
  985.     register long l;
  986.  
  987.     l = (hdr[ZP3] & 0377);
  988.     l = (l << 8) | (hdr[ZP2] & 0377);
  989.     l = (l << 8) | (hdr[ZP1] & 0377);
  990.     l = (l << 8) | (hdr[ZP0] & 0377);
  991.     return l;
  992. }
  993.  
  994. /* End of zm.c */
  995.